/**
 * 20182018年1月16日
 *
 * @author zhuwh4
 */
package com.utils.failureanalysis.data.util;

import com.utils.failureanalysis.data.dao.AnalysisDataRepository;
import com.utils.failureanalysis.data.dao.CountRecorderRepository;
import com.utils.failureanalysis.data.model.singleModule.CountRecorder;
import com.utils.failureanalysis.data.model.FilePath;
import com.utils.failureanalysis.data.model.singleRecorder.AnalysisData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipFile;

/**
 * 转成UTF-8进行读取
 *
 * @author zhuwh4
 *
 */
@Service
public class ParseResultFiles {
	@Autowired
    AnalysisDataRepository analysisDataRepository;
	@Autowired
    CountRecorderRepository countRecorderRepository;
	static final boolean isDebug = false;
	String debugFilePath = "./debug.log";
	String hostLogFolderPath;
	BufferedReader br;
	FilePath filePath;
	public static final String mSeparator = "$$";
	public static final String mSplit = "\\$\\$";
	List<String> parseFailResult = new ArrayList<>();
	List<String> parseHostLogZipResult = new ArrayList<>();
	String moduleName;
	private String taskId;
//	每个模块失败数统计
//	public static List<CountRecorder> countResult=new ArrayList<>();
//	每个模块详细分析统计
//	public static List<Recorder> result=new ArrayList<>();
//	每个模块的分析数据

	private ParseResultFiles(){}

	public ParseResultFiles(String taskId) {
		this.taskId = taskId;
	}

	public String getTaskId() {
		return taskId;
	}

	public void setTaskId(String taskId) {
		this.taskId = taskId;
	}

	/**
	 * 对单模块文件进行解析，结果添加到countResult和result中
	 *
	 * @param filePath
	 * @throws IOException
	 */
	public void parseModuleFiles(FilePath filePath) throws IOException {
		this.filePath = filePath;
//		caseName details 可能为空
		List<String> mDetails = parseFailResultFile(filePath.getFailResultFilePath());
//		modules num 非空
		String mNum = parseResultFile(filePath.getResultFilePath());
//		date caseName stackTrace非空
		List<String> mDate = parseHostLogZipFile(filePath.getHostLogZipFilePath(hostLogFolderPath));

//		获取modules 和 num
		String passNum = mNum.split(mSplit)[0];
		String failNum = mNum.split(mSplit)[1];
		String modules = mNum.split(mSplit)[2];
		moduleName = modules;

//		构建Recorder对象和CountRecorder对象
        countRecorderRepository.save(new CountRecorder(taskId,modules, passNum, failNum));

		for (String mString : mDetails) {
//			获取details
			String details = mString.split(mSplit)[1];
//			获取caseName
			String caseName = mString.split(mSplit)[0];
//			获取date和stackTrace
			String date = null;
			String stackTrace = null;
			for (String mmDate : mDate) {
				if (mmDate.split(mSplit)[1].contains(caseName)) {
					date = mmDate.split(mSplit)[0];
					if (mmDate.split(mSplit).length < 3) {
						if (isDebug) {
							System.out.println("*******" + mmDate + "*******");
							System.out.println("mmDate.split(mSplit).length is " + mmDate.split(mSplit).length);
							for (String s : mmDate.split(mSplit)) {
								System.out.println("%%%%%%%%" + s + "%%%%%%%%");
							}
						}
						System.out.println("-------can't find log of " + caseName + " in " + filePath.getHostLogZipFilePath(hostLogFolderPath).getParent().replaceAll(".*\\\\", "") + "\\" + filePath.getHostLogZipFilePath(hostLogFolderPath).getName() + "-------\r\n");
					}
					stackTrace = mmDate.split(mSplit).length > 2 ? mmDate.split(mSplit)[2] : "can't find log";
					break;
				}
			}
			String passOrFail = "fail";
//			analysisDataRepository.save(null);
            analysisDataRepository.save(new AnalysisData(taskId, modules, date, caseName, passOrFail, details, stackTrace));
        }
//		countRecorderRepository.save(countRecorder);
	}


	/**
	 * 解析test_result_failures.html
	 * 还要通过解析此xml确定host log存放的文件夹路径
	 *
	 * @param filePath
	 * @return 返回解析结果，以{@code mSeparator}分隔，如果没有fail项则返回null
	 * @throws IOException
	 */
	public List<String> parseFailResultFile(File filePath) throws IOException {
		// 清空历史存储的解析结果
		parseFailResult.clear();
		try {
			br = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "UTF-8"));
			// 解析出所有fail项的caseName
			String tempParse = "";
			boolean flag = false;
			for (String next = ""; next != null; next = br.readLine()) {
//				<td class="rowtitle">Start time / End Time</td><td>星期四 六月 21 17:24:49 CST 2018 /
				if (next.matches(".*\\d\\d:\\d\\d:\\d\\d CST .*")) {
					if (!flag)
						hostLogFolderPath = next.replaceAll("[^\\d :]", "").split(" +")[2].replace(":", ".");
					flag = true;
				}
				if (next.contains("class=\"testname\"")) {
					String caseName = next.replaceFirst("<td class=\"testname\">", "").split("<")[0];
					tempParse = caseName;
				}
				// 连上fail的details
				if (next.contains("class=\"details\"")) {
					String details = next.replaceFirst("<div class=\"details\">", "").split("&#13")[0];
					tempParse += mSeparator + details;
				}
				if (tempParse.split(mSplit).length > 1) {
					parseFailResult.add(tempParse);
					tempParse = "";
				}
			}
		} finally {
			br.close();
		}
		return parseFailResult;
	}

	/**
	 * 解析test_result.xml
	 *
	 * @param filePath
	 * @return 返回pass数及fail数与模块名，用{@code mSeparator}进行分割
	 * @throws IOException
	 */
	public String parseResultFile(File filePath) throws IOException {
		String parseResult = "";
		try {
			br = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "UTF-8"));
			for (String next = ""; next != null; next = br.readLine()) {
				// <Summary pass="11" failed="1" modules_done="1"
				// modules_total="1" />
				if (next.matches(".*Summary pass=.* modules_done=.* modules_total=.*")) {
					String pass = next.split("\"")[1];
					String fail = next.split("\"")[3];
					parseResult = pass + mSeparator + fail;
				}
				// <Module name="StatusBarprcTestCase" abi="arm64-v8a"
				// runtime="914712" done="true" pass="11">
				if (next.matches(".*Module name=.*")) {
					String module = next.split("\"")[1];
					parseResult += mSeparator + module;
				}
			}
		} finally {
			if (br != null)
				br.close();
		}
		return parseResult;
	}

	/**
	 * 解析host log
	 *
	 * @param filePath
	 * @return 返回case执行时间与case名及pass，fail
	 * @throws IOException
	 */
	public List<String> parseHostLogZipFile(File filePath) throws IOException {
		// 清空历史存储的解析结果
		parseHostLogZipResult.clear();
		try {
			// 对host log进行解析
			String line;
			ZipFile deviceLog = new ZipFile(filePath);
			// File deviceLog=new File("./src/test_result.xml");
			BufferedReader br = new BufferedReader(
					new InputStreamReader(deviceLog.getInputStream(deviceLog.entries().nextElement()), "GBK"));
			// 解析log
			boolean flag = false;
			while ((line = br.readLine()) != null) {
				String date, caseName, stackTrace;
//				仅解析出fail条目，如果需要解析出所有条目，使用正则：".* fail:.*"
				if (line.matches(".* pass$|.* fail:.*")) {
					flag = true;
					date = line.split(" ")[0] + " " + line.split(" ")[1];
					caseName = line.split("] ")[1].split(" ")[0];
					parseHostLogZipResult.add(date + mSeparator + caseName);
				}
//				获取exception堆栈信息
				if (flag && line.matches("at .*")) {
					stackTrace = line;
					while (line != null) {
						line = br.readLine();
						stackTrace += "\r\n" + line;
						if (!line.matches("at .*")) break;
					}
					parseHostLogZipResult.set(parseHostLogZipResult.size() - 1, parseHostLogZipResult.get(parseHostLogZipResult.size() - 1) + mSeparator + stackTrace);
				}
			}
			deviceLog.close();
		} finally {
			if (br != null)
				br.close();
		}
		return parseHostLogZipResult;
	}

	public String getModuleName() {
		return moduleName;
	}

	public void outputDebugLog() throws IOException {
//		true: 在文件末尾追加写入内容
		FileWriter fw = new FileWriter(new File(debugFilePath), true);
		fw.write("parseFailResult: \r\n");
		for (String str : parseFailResult) {
			fw.write(str + "\r\n");
		}
		fw.write("\r\n");
		fw.write("parseHostLogZipResult: \r\n");
		for (String str : parseHostLogZipResult) {
			fw.write(str + "\r\n");
		}
		fw.close();
	}

	// public void close(){
	// try {
	// if(br!=null)
	// br.close();
	// } catch (IOException e) {
	// TODO Auto-generated catch block
	// e.printStackTrace();
	// }
	// }
}
